package com.youlai.system.plugin.opcua;

import com.youlai.system.common.util.CommUtils;
import com.youlai.system.common.util.RedisUtil;
import com.youlai.system.global.EventHandler;
import com.youlai.system.helper.ApplicationContextHelper;
import com.youlai.system.manager.LanguageManager;
import com.youlai.system.model.entity.*;
import com.youlai.system.model.vo.OPCWriteNode;
import com.youlai.system.service.DMConfigService;
import com.youlai.system.service.EventTextConfigService;
import com.youlai.system.service.TrendConfigService;
import com.youlai.system.service.TrendLogsService;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.eclipse.milo.opcua.sdk.client.OpcUaClient;
import org.eclipse.milo.opcua.sdk.client.api.identity.AnonymousProvider;
import org.eclipse.milo.opcua.sdk.client.subscriptions.ManagedDataItem;
import org.eclipse.milo.opcua.sdk.client.subscriptions.ManagedSubscription;
import org.eclipse.milo.opcua.sdk.client.subscriptions.OpcUaSubscriptionManager;
import org.eclipse.milo.opcua.stack.core.UaException;
import org.eclipse.milo.opcua.stack.core.security.SecurityPolicy;
import org.eclipse.milo.opcua.stack.core.types.builtin.*;
import org.eclipse.milo.opcua.stack.core.types.builtin.unsigned.UInteger;
import org.eclipse.milo.opcua.stack.core.types.enumerated.TimestampsToReturn;
import org.springframework.stereotype.Component;

import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReentrantLock;
import java.util.function.BiPredicate;
import java.util.stream.Collectors;

/**
 * OpcUaHelper类用于帮助管理OPC UA客户端的连接和订阅。
 */
@Component
@Data
@Slf4j
public class OpcUaHelper {


    private final ReentrantLock lock = new ReentrantLock();
    public   TrendConfigService trendConfigService = ApplicationContextHelper.getBean(TrendConfigService.class);
    public TrendLogsService trendLogsService = ApplicationContextHelper.getBean(TrendLogsService.class);
    public EventTextConfigService eventTextConfigService = ApplicationContextHelper.getBean(EventTextConfigService.class);
    public DMConfigService dmConfigService = ApplicationContextHelper.getBean(DMConfigService.class);
    public  LanguageManager languageManager = ApplicationContextHelper.getBean(LanguageManager.class);

    public RedisUtil redisUtil = ApplicationContextHelper.getBean(RedisUtil.class);

    public OpcUaClient opcUaClient;
    public String endPointUrl;
    public boolean isConnected;
    public boolean isSubscribed;
    private OpcUaSubscriptionManager opcuaSubscriptionManager;
    private List<NodeId> subscriptionItems;
    private List<NodeId> subscriptionDMItems;
    private ManagedDataItem.DataValueListener subscriptionListener;
    private ManagedDataItem.DataValueListener subscriptionDMListener;
    private ManagedSubscription manageSubscription;

    /**
     * 默认构造函数。
     */
    public OpcUaHelper(){

    }

    /**
     * 尝试建立OPC UA客户端连接。
     *
     * @throws Exception 如果连接过程中出现异常
     */
    public OpcUaHelper(String ip, int port){
        endPointUrl = "opc.tcp://" + ip + ":" + port;
    }

    /**
     * 示例方法：创建OPC UA客户端。
     *
     * @return 新创建的OPC UA客户端实例
     */
    public void Connect() throws Exception {
        lock.lock();
        try {
            //创建OPC UA客户端
            opcUaClient = createClient();
            //开启连接
            opcUaClient.connect().get();
            //添加订阅管理
            manageSubscription = ManagedSubscription.create(opcUaClient);
            opcuaSubscriptionManager = opcUaClient.getSubscriptionManager();
            //添加订阅监听器，用于处理断线重连后的订阅问题
            opcuaSubscriptionManager.addSubscriptionListener(new CustomSubscriptionListener(this));
            isConnected = true;
        } finally {
            lock.unlock();
        }
    }

    /**
     * 自定义订阅监听器。
     */
    public void Connect(String ip, int port) throws Exception {
        endPointUrl = "opc.tcp://" + ip + ":" + port;
        lock.lock();
        try {
            //创建OPC UA客户端
            opcUaClient = createClient();
            //开启连接
            opcUaClient.connect().get();
            //添加订阅管理
            manageSubscription = ManagedSubscription.create(opcUaClient);
            opcuaSubscriptionManager = opcUaClient.getSubscriptionManager();
            //添加订阅监听器，用于处理断线重连后的订阅问题
            opcuaSubscriptionManager.addSubscriptionListener(new CustomSubscriptionListener(this));
            isConnected = true;
        } finally {
            lock.unlock();
            if(!isConnected){
                EventHandler.Add("连接PLC",
                        EventHandler.Type.DEVICE,
                        EventHandler.DeviceGroup.GROUP1,
                        "现场设备",
                        "S7-1500",
                        EventHandler.MessageType.FAULT,
                        "PLC连接失败请检查参数，或者网络"
                );
            }
        }
    }


    public void DisConnect() {
        lock.lock();
        try {
            isConnected = false;
            isSubscribed = false;
//            SubscriptionCancel();
            opcUaClient.disconnect();
            opcuaSubscriptionManager = null;
            opcUaClient = null;
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }

    private OpcUaClient createClient() throws Exception {
        Path securityTempDir = Paths.get(System.getProperty("java.io.tmpdir"), "security");
        Files.createDirectories(securityTempDir);
        if (!Files.exists(securityTempDir)) {
            throw new Exception("unable to create security dir: " + securityTempDir);
        }
        return OpcUaClient.create(endPointUrl,
                endpoints ->
                        endpoints.stream()
                                .filter(e -> e.getSecurityPolicyUri().equals(SecurityPolicy.None.getUri()))
                                .findFirst(),
                configBuilder ->
                        configBuilder
                                .setApplicationName(LocalizedText.english("opc-ua"))
                                .setApplicationUri("")
                                .setIdentityProvider(new AnonymousProvider())
                                .setRequestTimeout(UInteger.valueOf(5000))
                                .build()
        );
    }

    public void SetSubscriptionItems(List<String> nodeIdStrList, ManagedDataItem.DataValueListener subscriptionListener) {
        lock.lock();
        try {
            subscriptionItems = new ArrayList<>();
            for (var nodeIdStr : nodeIdStrList) {
                subscriptionItems.add(NodeId.parse(nodeIdStr));
            }
            this.subscriptionListener = subscriptionListener;
        } finally {
            lock.unlock();
        }
    }

    public void SetSubscriptionDMItems(List<String> nodeIdStrList, ManagedDataItem.DataValueListener subscriptionListener) {
        lock.lock();
        try {
            subscriptionDMItems = new ArrayList<>();
            for (var nodeIdStr : nodeIdStrList) {
                subscriptionDMItems.add(NodeId.parse(nodeIdStr));
            }
            this.subscriptionDMListener = subscriptionListener;
        } finally {
            lock.unlock();
        }
    }


    public void SubscriptionHandler() throws UaException {
        lock.lock();
        manageSubscription.getSubscription();
        try {
            if (subscriptionItems != null && !subscriptionItems.isEmpty()) {
                List<ManagedDataItem> dataItemList = manageSubscription.createDataItems(subscriptionItems);
                System.out.println(dataItemList);
                for (var item : dataItemList) {
                    item.addDataValueListener(subscriptionListener);
                }
            }
        } finally {
            lock.unlock();
        }
    }

    public void SubscriptionDMHandler() throws UaException {
        lock.lock();
        manageSubscription.getSubscription();
        try {
            if (subscriptionDMItems != null && !subscriptionDMItems.isEmpty()) {
                List<ManagedDataItem> dataItemList = manageSubscription.createDataItems(subscriptionDMItems);
                System.out.println(dataItemList);
                for (var item : dataItemList) {
                    item.addDataValueListener(subscriptionDMListener);
                }
            }
        } finally {
            lock.unlock();
        }
    }

    public void SubscriptionCancel() throws UaException {
        lock.lock();
        try {
            isSubscribed = false;
            for(var item : manageSubscription.getDataItems()){
                item.removeDataValueListener(subscriptionListener);
            }
            for(var item : manageSubscription.getDataItems()){
                item.removeDataValueListener(subscriptionDMListener);
            }
            // 清空数据项列表
//            manageSubscription.getDataItems().clear();

            System.out.println(manageSubscription.getDataItems());
//            manageSubscription.delete();
            subscriptionItems.clear();
            subscriptionDMItems.clear();
            subscriptionListener = null;
            subscriptionDMListener = null;
        } finally {
            lock.unlock();
        }
    }

    public DataValue ReadValue(String nodeIdStr) throws ExecutionException, InterruptedException {
        NodeId nodeId = NodeId.parse(nodeIdStr);
        return opcUaClient.readValue(0.0, TimestampsToReturn.Both, nodeId).get();
    }


    /**
     * 异步批量向PLC写入多个值。
     *
     * @param opcWriteNodeList 包含节点ID和值的列表
     * @return CompletableFuture<Boolean> 表示批量写入操作的结果
     */
    public CompletableFuture<Boolean> writeValuesAsync(List<OPCWriteNode> opcWriteNodeList) {
        List<NodeId> nodeIds = new ArrayList<>();
        List<DataValue> dataValues = new ArrayList<>();

        // 将nodeIdStrs和values转换为NodeIds和DataValues
        for (OPCWriteNode node : opcWriteNodeList) {
            String nodeIdStr = node.getNodeId().trim();
            Object value = node.getValue();

            // 将value转换为Short类型
            Object shortValue = convertValue(value,node.getValueType());

            // 创建Variant对象
            Variant variant = new Variant(shortValue);
            DataValue dataValue = new DataValue(variant, null, null);

            nodeIds.add(NodeId.parse(nodeIdStr));
            dataValues.add(dataValue);
        }

        // 异步批量写入值
        return opcUaClient.writeValues(nodeIds, dataValues)
                .thenApply(statusCodes -> {
                    // 检查所有状态码是否都为良好
                    return statusCodes.stream().allMatch(StatusCode::isGood);
                });
    }

    /**
     * 将值转换为Short类型。
     *
     * @param value 要转换的值
     * @return 转换后的Short类型值
     * @throws IllegalArgumentException 如果转换失败
     */
    private Short toShort(Object value) {
        if (value instanceof Number) {
            return ((Number) value).shortValue();
        } else if (value instanceof String) {
            try {
                return Short.parseShort((String) value);
            } catch (NumberFormatException e) {
                throw new IllegalArgumentException("值不能转换为Int16类型", e);
            }
        } else {
            throw new IllegalArgumentException("不支持的类型: " + value.getClass().getName());
        }
    }

    /**
     * 根据给定的类型转换值。
     *
     * @param value      要转换的原始值
     * @param valueType  目标类型
     * @return 转换后的值
     * @throws IllegalArgumentException 如果转换失败
     */
    private Object convertValue(Object value, Class<?> valueType) {
        if (valueType.isInstance(value)) {
            return value;
        } else if (valueType.equals(Short.class) || valueType.equals(Short.TYPE)) {
            if (value instanceof Number) {
                return ((Number) value).shortValue();
            } else if (value instanceof String) {
                try {
                    return Short.parseShort((String) value);
                } catch (NumberFormatException e) {
                    throw new IllegalArgumentException("值不能转换为目标类型", e);
                }
            }
        } else if (valueType.equals(Integer.class) || valueType.equals(Integer.TYPE)) {
            if (value instanceof Number) {
                return ((Number) value).intValue();
            } else if (value instanceof String) {
                try {
                    return Integer.parseInt((String) value);
                } catch (NumberFormatException e) {
                    throw new IllegalArgumentException("值不能转换为目标类型", e);
                }
            }
        } else if (valueType.equals(Float.class) || valueType.equals(Float.TYPE)) {
            if (value instanceof Number) {
                return ((Number) value).floatValue();
            } else if (value instanceof String) {
                try {
                    return Float.parseFloat((String) value);
                } catch (NumberFormatException e) {
                    throw new IllegalArgumentException("值不能转换为目标类型", e);
                }
            }
        } else if (valueType.equals(Double.class) || valueType.equals(Double.TYPE)) {
            if (value instanceof Number) {
                return ((Number) value).doubleValue();
            } else if (value instanceof String) {
                try {
                    return Double.parseDouble((String) value);
                } catch (NumberFormatException e) {
                    throw new IllegalArgumentException("值不能转换为目标类型", e);
                }
            }
        } else if (valueType.equals(Long.class) || valueType.equals(Long.TYPE)) {
            if (value instanceof Number) {
                return ((Number) value).longValue();
            } else if (value instanceof String) {
                try {
                    return Long.parseLong((String) value);
                } catch (NumberFormatException e) {
                    throw new IllegalArgumentException("值不能转换为目标类型", e);
                }
            }
        }
        throw new IllegalArgumentException("不支持的类型: " + valueType.getName());
    }

    /**
     * 检查写入操作是否成功。
     *
     * @param statusCode 状态码
     * @return 操作是否成功
     */
    private Boolean isOperationSuccessful(StatusCode statusCode) {
        return statusCode.isGood();
    }

    /*
    节点自动转换工具
    输入DBLine.Real1
    输出ns=3;s="DBLine"."Real1"
     */
    public  String FormatNodeId(String nodeName) {
        // 检查节点名称是否包含 []
        boolean isArrayIndex = nodeName.contains("[");

        StringBuilder sb = new StringBuilder();
        sb.append("ns=3;s=");
        sb.append('"').append(nodeName.split("\\.")[0]).append('"'); // 添加第一个部分并用双引号包围

        String[] parts = nodeName.split("(?<=\\.)|(?=\\[)|(?<=\\])");
        for (int i = 1; i < parts.length; i++) {
            if (i % 2 == 1) { // 处理中间部分，如 "ArrReal"
                sb.append('.').append('"').append(parts[i]).append('"');
            } else if (isArrayIndex) { // 处理索引部分，如 [0]
                sb.append(parts[i]);
            }
        }

        return sb.toString();
    }

    /**
     * 格式化节点名称为标准的OPC UA节点ID格式。
     *
     * @param nodeNames 节点名称列表
     * @return 格式化后的节点ID列表
     */
    public List<String> FormatNodeIds(List<String> nodeNames) {
        List<String> formattedNodeIds = new ArrayList<>();

        // 遍历节点名称列表
        for (String nodeName : nodeNames) {
            // 检查节点名称是否包含 []，表示数组索引
            boolean isArrayIndex = nodeName.contains("[");

            // 使用StringBuilder来构建格式化的节点ID
            StringBuilder sb = new StringBuilder();
            sb.append("ns=3;s="); // 添加命名空间和分隔符

            // 提取节点名称的第一部分，并用双引号包围
            sb.append('"').append(nodeName.split("\\.")[0]).append('"');

            // 分割节点名称，处理中间部分（如ArrReal）和索引部分（如[0]）
            String[] parts = nodeName.split("(?<=\\.)|(?=\\[)|(?<=\\])");
            for (int i = 1; i < parts.length; i++) {
                if (i % 2 == 1) { // 处理中间部分，如 "ArrReal"
                    sb.append('.').append('"').append(parts[i]).append('"');
                } else if (isArrayIndex) { // 处理索引部分，如 [0]
                    sb.append(parts[i]);
                }
            }

            // 将格式化后的节点ID添加到结果列表中
            formattedNodeIds.add(sb.toString());
        }

        // 返回格式化后的节点ID列表
        return formattedNodeIds;
    }

    /**
     * 启动OPC UA订阅，并处理数据值更新。
     *
     * @param list 要订阅的节点ID列表
     * @param listener 数据值更新监听器
     * @throws Exception 如果订阅过程中发生错误
     */
    public void StartSubscription(List<String> list, ManagedDataItem.DataValueListener listener) throws Exception {
        // 标记订阅状态
        isSubscribed = true;

        try {
            // 创建一个匿名内部类作为数据值监听器
            listener = (item, value) -> {
                // 获取节点ID
                String address = CommUtils.FormatNode((String) item.getReadValueId().getNodeId().getIdentifier());
                // 格式化浮点数值
                String valueStr = CommUtils.FormatFloat((Float) value.getValue().getValue());

                // 日志输出订阅的节点ID和对应的值
                log.info("----Trend-----订阅nodeid------- :" + address);
                log.info("----Trend-----订阅value---------  :" + valueStr);

                // 将趋势日志写入数据库
                WriteTrendLogsToDB(address, valueStr);
            };

            // 设置订阅项
            SetSubscriptionItems(list, listener);

            // 处理订阅
            try {
                SubscriptionHandler();
            } catch (UaException e) {
                throw new RuntimeException(e);
            }

            // 持续订阅
            try {
                // 阻塞当前线程，使订阅持续运行
                Thread.sleep(Long.MAX_VALUE);
            } catch (InterruptedException e) {
                // 如果线程被中断，抛出异常
                throw new RuntimeException(e);
            }
        } catch (Exception e) {
            // 如果发生异常，重置订阅状态
            isSubscribed = false;
            throw new RuntimeException("订阅节点失败，请检查节点有效性: " + e.getMessage(), e);
        }
    }

    /**
     * 启动OPC UA订阅，并处理数据值更新。
     *
     * @param list 要订阅的节点ID列表
     * @param listener 数据值更新监听器
     * @throws Exception 如果订阅过程中发生错误
     */
    public void StartSubscriptionDM(List<String> list, ManagedDataItem.DataValueListener listener) throws Exception {
        // 标记订阅状态
        isSubscribed = true;

        try {
            // 创建一个匿名内部类作为数据值监听器
            listener = (item, value) -> {
                // 获取节点ID
                String address = CommUtils.FormatNode((String) item.getReadValueId().getNodeId().getIdentifier());
                // 格式化
                Boolean result = (Boolean) value.getValue().getValue();

                // 日志输出订阅的节点ID和对应的值
                log.info("-----DM----订阅nodeid------- :" + address);
                log.info("-----DM----订阅value---------  :" + result);

                // 将趋势日志写入数据库
                //WriteTrendLogsToDB(address, valueStr);

                //启动事件
                if(result){
                    try {
                        DMWriteToDB(address);
                    } catch (Exception e) {
                        throw new RuntimeException(e);
                    }
                }
            };

            // 设置订阅项
            SetSubscriptionDMItems(list, listener);

            // 处理订阅
            try {
                SubscriptionDMHandler();
            } catch (UaException e) {
                throw new RuntimeException(e);
            }

            // 持续订阅
            try {
                // 阻塞当前线程，使订阅持续运行
                Thread.sleep(Long.MAX_VALUE);
            } catch (InterruptedException e) {
                // 如果线程被中断，抛出异常
                throw new RuntimeException(e);
            }
        } catch (Exception e) {
            // 如果发生异常，重置订阅状态
            isSubscribed = false;
            throw new RuntimeException("订阅节点失败，请检查节点有效性: " + e.getMessage(), e);
        }
    }

    public void DMWriteToDB(String address) throws Exception {
            // 通过地址获取DMConfig
            DMConfig dmConfig = dmConfigService.getDMByAddress(address);
            if (dmConfig == null) {
                throw new IllegalArgumentException("DMConfig not found for address: " + address);
            }

            // 通过地址获取EventText
            EventText eventText = eventTextConfigService.getEventTextByTextId(dmConfig.getTextId());
            if (eventText == null) {
                throw new IllegalArgumentException("EventText not found for textId: " + dmConfig.getTextId());
            }

            // 定义消息类型
            EventHandler.MessageType messageType = determineMessageType(eventText.getTextId());

            // 定义文本类型
            String languageText = determineLanguageText(languageManager.getCurrentLanguage(), eventText);
            // 获取本身信息
            EventHandler.Add("订阅PLC",
                    EventHandler.Type.ADDRESS,
                    EventHandler.DeviceGroup.GROUP1,
                    address,
                    "S7-1500",
                    messageType,
                    languageText
            );


    }


    /**
     * 根据消息ID的前缀确定消息类型。
     *
     * @param textId 消息ID
     * @return 消息类型
     * @throws IllegalArgumentException 如果消息ID前缀未知
     */
    private EventHandler.MessageType determineMessageType(String textId) {
        char firstChar = textId.toUpperCase().charAt(0);
        switch (firstChar) {
            case 'E':
                return EventHandler.MessageType.MESSAGE;
            case 'W':
                return EventHandler.MessageType.WARNING;
            case 'F':
                return EventHandler.MessageType.FAULT;
            default:
                throw new IllegalArgumentException("Unknown message type prefix: " + textId);
        }
    }

    /**
     * 根据语言代码确定语言文本。
     *
     * @param language 语言代码
     * @param eventText 事件文本配置
     * @return 语言文本
     * @throws IllegalArgumentException 如果语言代码未知
     */
    private String determineLanguageText(String language, EventText eventText) {
        switch (language) {
            case "ZH_CN":
                return eventText.getZhCn();
            case "EN_US":
                return eventText.getEnUs();
            case "DE_DE":
                return eventText.getDeDe();
            case "KO_KR":
                return eventText.getKoKr();
            default:
                throw new IllegalArgumentException("Unknown language code: " + language);
        }
    }



    /*
    筛选获取所有enable=true 的
     */
    public List<String> AllTrendNodes(){
        //获取Bean
       TrendConfigService trendConfigService = ApplicationContextHelper.getBean(TrendConfigService.class);

        List<TrendConfig> allTrendConfigs = trendConfigService.list();

        // 使用 Stream API 过滤出 enable 为 true 的实体
        List<TrendConfig> enabledTrendConfigs = allTrendConfigs.stream()
                .filter(config -> config.getEnable())
                .collect(Collectors.toList());
        List<String> nodeItems = enabledTrendConfigs.stream()
                .map(TrendConfig::getAddress)
                .collect(Collectors.toList());
        return nodeItems;
    }

    /*
筛选获取所有enable=true 的
 */
    public List<String> AllDMNodes(){
        //获取Bean
        DMConfigService dmConfigService = ApplicationContextHelper.getBean(DMConfigService.class);

        List<DMConfig> allDMConfigs = dmConfigService.list();

        // 使用 Stream API 过滤出 enable 为 true 的实体
        List<DMConfig> enabledTrendConfigs = allDMConfigs.stream()
                .filter(config -> config.getEnable())
                .collect(Collectors.toList());
        List<String> nodeItems = enabledTrendConfigs.stream()
                .map(DMConfig::getAddress)
                .collect(Collectors.toList());
        return nodeItems;
    }
    /**
     * 将趋势日志写入数据库。
     *
     * @param address 节点地址
     * @param value 节点值
     */
    public void WriteTrendLogsToDB(String address, String value) {
        try {
            /**
             * Redis操作
             */
            // 获取Redis中的数据
            RedisNode redisData = (RedisNode) redisUtil.get(address);

            // 初次执行时初始化Redis数据
            try {
                if (redisData == null) {
                    RedisNode redisNode = new RedisNode();
                    redisNode.setCurrentValue(value);
                    redisNode.setPreviousValue(value);
                    redisNode.setTrendConfig(trendConfigService.getTrendConfigByAddress(address));
                    redisUtil.set(address, redisNode, 1, TimeUnit.DAYS);
                }
            } catch (Exception e) {
                throw new RuntimeException("Redis内未找到 " + address + " 开始自动生成", e);
            }

            // 从Redis中获取趋势配置
            TrendConfig trendConfig = redisData.getTrendConfig();

            // 实例化新的RedisNode对象
            RedisNode redisNode = new RedisNode();
            redisNode.setPreviousValue(redisData.getCurrentValue());
            redisNode.setCurrentValue(value);
            redisNode.setTrendConfig(trendConfig);

            // 计算当前值与上一个值之间的差值
            Float currentValue = Float.valueOf(value);
            Float previousValue = Float.valueOf(redisData.getPreviousValue());
            Integer tolerance = Integer.valueOf(trendConfig.getParameter());

            // 判断是否需要记录趋势日志
            if (CommUtils.IsWithinTolerance(currentValue, previousValue, tolerance)) {
                // 创建TrendLogs对象
                TrendLogs trendLogs = new TrendLogs();
                trendLogs.setDevice(trendConfig.getDevice());
                trendLogs.setAddress(trendConfig.getAddress());
                trendLogs.setType(trendConfig.getType());
                trendLogs.setValue(value);
                trendLogs.setUnit(trendConfig.getUnit());
                trendLogs.setTime(CommUtils.getCurrentDateTime());
                trendLogs.setDescription(trendConfig.getDescription());

                // 保存趋势日志到数据库
                trendLogsService.save(trendLogs);
            }

            EventText eventText = new EventText();

            //----------------------------判断报警 L LL H HH------------------------------------
//            if((currentValue > Float.valueOf(trendConfig.getHParameter())) && trendConfig.getHEnable() == true){
//                //从数据库找相应文本
//                eventText = eventTextConfigService.getEventTextByTextId(trendConfig.getHTextId());
//                if (eventText == null) {
//                    throw new IllegalArgumentException("EventText not found for textId: " + trendConfig.getHTextId());
//                }
//                //定义消息类型
//                EventHandler.MessageType messageType = determineMessageType(eventText.getTextId());
//                //多语言
//                String languageText = determineLanguageText(languageManager.getCurrentLanguage(),eventText);
//                //写入对应记录
//                EventHandler.Add("订阅",
//                        EventHandler.Type.ADDRESS,
//                        EventHandler.DeviceGroup.GROUP1,
//                        address,
//                        "S7-1500",
//                        messageType,
//                        languageText
//                );
//            }
//            if((currentValue > Float.valueOf(trendConfig.getHHParameter())) && trendConfig.getHHEnable() == true){
//                //从数据库找相应文本
//                eventText = eventTextConfigService.getEventTextByTextId(trendConfig.getHHTextId());
//                if (eventText == null) {
//                    throw new IllegalArgumentException("EventText not found for textId: " + trendConfig.getHHTextId());
//                }
//                //定义消息类型
//                EventHandler.MessageType messageType = determineMessageType(eventText.getTextId());
//                //多语言
//                String languageText = determineLanguageText(languageManager.getCurrentLanguage(),eventText);
//                //写入对应记录
//                EventHandler.Add("订阅",
//                        EventHandler.Type.ADDRESS,
//                        EventHandler.DeviceGroup.GROUP1,
//                        address,
//                        "S7-1500",
//                        messageType,
//                        languageText
//                );
//            }
//            if((currentValue < Float.valueOf(trendConfig.getLParameter())) && trendConfig.getLEnable() == true){
//                //从数据库找相应文本
//                eventText = eventTextConfigService.getEventTextByTextId(trendConfig.getLTextId());
//                if (eventText == null) {
//                    throw new IllegalArgumentException("EventText not found for textId: " + trendConfig.getLTextId());
//                }
//                //定义消息类型
//                EventHandler.MessageType messageType = determineMessageType(eventText.getTextId());
//                //多语言
//                String languageText = determineLanguageText(languageManager.getCurrentLanguage(),eventText);
//                //写入对应记录
//                EventHandler.Add("订阅",
//                        EventHandler.Type.ADDRESS,
//                        EventHandler.DeviceGroup.GROUP1,
//                        address,
//                        "S7-1500",
//                        messageType,
//                        languageText
//                );
//            }
//            if((currentValue < Float.valueOf(trendConfig.getHParameter())) && trendConfig.getLLEnable() == true){
//                //从数据库找相应文本
//                eventText = eventTextConfigService.getEventTextByTextId(trendConfig.getLLTextId());
//                if (eventText == null) {
//                    throw new IllegalArgumentException("EventText not found for textId: " + trendConfig.getLLTextId());
//                }
//                //定义消息类型
//                EventHandler.MessageType messageType = determineMessageType(eventText.getTextId());
//                //多语言
//                String languageText = determineLanguageText(languageManager.getCurrentLanguage(),eventText);
//                //写入对应记录
//                EventHandler.Add("订阅",
//                        EventHandler.Type.ADDRESS,
//                        EventHandler.DeviceGroup.GROUP1,
//                        address,
//                        "S7-1500",
//                        messageType,
//                        languageText
//                );
//            }




            // 将更新后的RedisNode对象写回Redis

            processTrendConfig(currentValue,trendConfig,address);

            redisUtil.set(address, redisNode, 1, TimeUnit.DAYS);

        } catch (Exception exception) {
            // 如果发生异常，则重新抛出
            throw exception;
        }
    }

    public void processTrendConfig(Float currentValue, TrendConfig trendConfig, String address) {
        checkAndHandleThreshold(currentValue,address, trendConfig.getHParameter(), trendConfig.getHEnable(), trendConfig.getHTextId(), (a, b) -> a > b, "H");
        checkAndHandleThreshold(currentValue, address,trendConfig.getHHParameter(), trendConfig.getHHEnable(), trendConfig.getHHTextId(), (a, b) -> a > b, "HH");
        checkAndHandleThreshold(currentValue,address, trendConfig.getLParameter(), trendConfig.getLEnable(), trendConfig.getLTextId(), (a, b) -> a < b, "L");
        checkAndHandleThreshold(currentValue,address, trendConfig.getLLParameter(), trendConfig.getLLEnable(), trendConfig.getLLTextId(), (a, b) -> a < b, "LL");
    }

    private void checkAndHandleThreshold(Float currentValue, String address, String parameter, Boolean enable, String textId, BiPredicate<Float, Float> condition, String thresholdType) {
        if (enable != null && enable && condition.test(currentValue, Float.valueOf(parameter))) {
            EventText eventText = eventTextConfigService.getEventTextByTextId(textId);
            if (eventText == null) {
                throw new IllegalArgumentException("EventText not found for textId: " + textId);
            }
            EventHandler.MessageType messageType = determineMessageType(eventText.getTextId());
            String languageText = determineLanguageText(languageManager.getCurrentLanguage(), eventText);
            EventHandler.Add("订阅",
                    EventHandler.Type.ADDRESS,
                    EventHandler.DeviceGroup.GROUP1,
                    address,
                    "S7-1500",
                    messageType,
                    languageText
            );
        }
    }
}

